home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / dev / lang / python020.lha / python / lib / whrandom.py < prev    next >
Text File  |  1995-10-22  |  2KB  |  99 lines

  1. #    WICHMANN-HILL RANDOM NUMBER GENERATOR
  2. #
  3. #    Wichmann, B. A. & Hill, I. D. (1982)
  4. #    Algorithm AS 183: 
  5. #    An efficient and portable pseudo-random number generator
  6. #    Applied Statistics 31 (1982) 188-190
  7. #
  8. #    see also: 
  9. #        Correction to Algorithm AS 183
  10. #        Applied Statistics 33 (1984) 123  
  11. #
  12. #        McLeod, A. I. (1985)
  13. #        A remark on Algorithm AS 183 
  14. #        Applied Statistics 34 (1985),198-200
  15. #
  16. #
  17. #    USE:
  18. #    whrandom.random()    yields double precision random numbers 
  19. #                uniformly distributed between 0 and 1.
  20. #
  21. #    whrandom.seed(x, y, z)    must be called before whrandom.random()
  22. #                to seed the generator
  23. #
  24. #    There is also an interface to create multiple independent
  25. #    random generators, and to choose from other ranges.
  26.  
  27.  
  28. #    Translated by Guido van Rossum from C source provided by
  29. #    Adrian Baddeley.
  30.  
  31.  
  32. class whrandom:
  33.     #
  34.     # Initialize an instance.
  35.     # Without arguments, initialize from current time.
  36.     # With arguments (x, y, z), initialize from them.
  37.     #
  38.     def __init__(self, x = 0, y = 0, z = 0):
  39.         self.seed(x, y, z)
  40.     #
  41.     # Set the seed from (x, y, z).
  42.     # These must be integers in the range [0, 256).
  43.     #
  44.     def seed(self, x = 0, y = 0, z = 0):
  45.         if not type(x) == type(y) == type(z) == type(0):
  46.             raise TypeError, 'seeds must be integers'
  47.         if not 0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256:
  48.             raise ValueError, 'seeds must be in range(0, 256)'
  49.         if 0 == x == y == z:
  50.             # Initialize from current time
  51.             import time
  52.             t = int(time.time() % 0x80000000)
  53.             t, x = divmod(t, 256)
  54.             t, y = divmod(t, 256)
  55.             t, z = divmod(t, 256)
  56.         self._seed = (x, y, z)
  57.     #
  58.     # Get the next random number in the range [0.0, 1.0).
  59.     #
  60.     def random(self):
  61.         x, y, z = self._seed
  62.         #
  63.         x1, x2 = divmod(x, 177)
  64.         y1, y2 = divmod(y, 176)
  65.         z1, z2 = divmod(z, 178)
  66.         #
  67.         x = (171 * x2 -  2 * x1) % 30269
  68.         y = (172 * y2 - 35 * y1) % 30307
  69.         z = (170 * z2 - 63 * z1) % 30323
  70.         #
  71.         self._seed = x, y, z
  72.         #
  73.         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
  74.     #
  75.     # Get a random number in the range [a, b).
  76.     #
  77.     def uniform(self, a, b):
  78.         return a + (b-a) * self.random()
  79.     #
  80.     # Get a random integer in the range [a, b] including both end points.
  81.     #
  82.     def randint(self, a, b):
  83.         return a + int(self.random() * (b+1-a))
  84.     #
  85.     # Choose a random element from a non-empty sequence.
  86.     #
  87.     def choice(self, seq):
  88.         return seq[int(self.random() * len(seq))]
  89.  
  90.  
  91. # Initialize from the current time
  92. #
  93. _inst = whrandom()
  94. seed = _inst.seed
  95. random = _inst.random
  96. uniform = _inst.uniform
  97. randint = _inst.randint
  98. choice = _inst.choice
  99.